

#include "../include/rdma_transporter.h"

#include <gtest/gtest.h>
#include <chrono>
#define N 1000
struct message {
	uint32_t msg_size;
	char *buf;
};


char *gen_random_string(size_t len){
	int flag;
	char *str;
	srand((unsigned) time(NULL));
	str = (char *) malloc(len + 1);
	for(int i = 0; i < len; i++){
		flag = rand() % 3;
		switch(flag){
			case 0:
				str[i] = 'A' + rand() % 26;
				break;
			case 1:
				str[i] = 'a' + rand() % 26;
				break;
			case 2:
				str[i] = '0' + rand() % 10;
				break;
			default:
				str[i] = 'x';
				break;
		}
	}
	str[len] = '1';
	return str;

}

int gen_send_buf(char *s, message *msg){
    memcpy(s, &msg->msg_size, sizeof(uint32_t));
    s[4] = '1';
    memcpy(s + 5, msg->buf, msg->msg_size  + 1);
    return 0;
}


void init(rdma_fd *handler){
    char *server = "tstore01";
    uint16_t port = 9005;
    int sock = client_exchange(server, port);
    handler->fd = sock;
    context_info *ib_info = (context_info *)malloc(sizeof(context_info));
    open_device_and_alloc_pd(ib_info);
    get_context_info(handler, ib_info);
    build_rdma_connection(handler);
}

TEST(RDMA_Test,Latency){
	rdma_fd *handler = (rdma_fd *)malloc(sizeof(rdma_fd));
	init(handler);
	message *msg = (message *) malloc(sizeof(message));
	//char *first_section = (char *)malloc(sizeof(char) * 5);
    int test_array[5] = {8, 32, 128, 512, 2048};
    for(int i = 0; i < 5; i++){
    	msg->msg_size = test_array[i];
    	msg->buf = gen_random_string(msg->msg_size);
    	char *s = (char *)malloc(msg->msg_size + 1 + 4 + 1);
	    gen_send_buf(s, msg);
	    auto start = std::chrono::system_clock::now();
	    for(int i = 0; i < N; i++){
	    	rdma_write(handler, s, msg->msg_size + 1 + 4 + 1);
	    	//rdma_write(handler, msg->buf, msg->msg_size + 1);
	    	read_msg(handler);
	    }
	    auto end = std::chrono::system_clock::now();
	    std::chrono::duration<double> diff = end-start;
	    printf("[Size]: %d Bytes [TIME]: %lf [Latency]: %lf us\n", 
	    		test_array[i], diff.count(), (double) diff.count() * 1000000 / N);
	    free(s);
    }

}

int main(int argc, char * argv[]){
    testing::InitGoogleTest(&argc, argv);  
    return RUN_ALL_TESTS();  

}